import { creepNameToObj, roomNameToObj } from "../baseTools"
import { creepIsTired, getBodymoduleCount } from "./creepTool"

const roomTool = {
    /**A*寻路
     * 1. 支持使用数组[pos1,pos2,pos3]寻找ori到目的地最近路径,注意只支持同一个房间
     * @param {RoomPosition} ori 起点
     * @param {*} target 单个包含RoomPosition对象或者该数组
     * @param {*} option range 寻址范围,creep 是否应用creep
     * @returns path
     */
    findPathByAStar: function (ori, target, option = {}) {
        let { range = 1, creep = null, byAutoBuild = false } = option
        if (typeof (creep) === 'string') creep = Game.creeps[creep]
        // console.log(JSON.stringify(target));
        if (!Array.isArray(target) && (!target['pos'])) {
            if (!target['x'] && !target['y'] && !target['roomName']) return null
            target.pos = new RoomPosition(target.x, target.y, target.roomName)
        }
        ori = new RoomPosition(ori.x, ori.y, ori.roomName)
        /**先判断当前房间是否处于纳入统计的房间 */
        if (!Memory.rooms[ori.roomName]) return null // 未被纳入返回null，建议使用moveTo方法
        // // 被纳入统计则优先使用A*算法
        const costM = PathFinder.CostMatrix.deserialize(Memory.rooms[ori.roomName]['terrain']['costMatrix'])
        if (Array.isArray(target)) {
            // console.log(`${JSON.stringify(target)}数组?`);
            target = target.map(t => { return { 'pos': !target['pos'] ? t.pos : t, 'range': range } })
        } else {
            // 避免入错参数
            if (!target['range']) {
                target = Object.assign({}, { 'pos': target.pos, 'range': range })
            } else {
                target = Object.assign({}, { 'pos': target.pos, 'range': target.range })
            }
        }
        // 只是单纯的需要路径，因此不需要传入creep
        if (!creep) {
            // console.log('不需要creep，只需要路径');
            if (!byAutoBuild) {
                return PathFinder.search(ori, target, { plainCost: 3, swampCost: 10, roomCallback: costM })
            } else {
                return PathFinder.search(ori, target, { plainCost: 2, swampCost: 25, roomCallback: costMatrix })
            }
        }
        /**关于疲劳值和移动路线的选择
         * 1. 存在负疲劳值则优先走道路
         * 2. 无疲劳值则走平原
         */
        let plainCost
        let moveCout = 0
        let tiredCount = 0
        let bodyTypeObj = getBodymoduleCount(creep.name)
        if (creep.store.getUsedCapacity() == 0) {
            // 空载状态，carry不纳入计算
            Object.keys(bodyTypeObj).filter(bodyType => bodyType != CARRY).map(bodyType => {
                bodyType == MOVE ? moveCout += bodyTypeObj[bodyType] : tiredCount += bodyTypeObj[bodyType]
            })
        } else {
            // 非空载状态，carry纳入计算
            Object.keys(bodyTypeObj).map(bodyType => {
                bodyType == MOVE ? moveCout += bodyTypeObj[bodyType] : tiredCount += bodyTypeObj[bodyType]
            })
        }
        // 产出大于消耗则走平原
        moveCout >= tiredCount ? plainCost = 1 : plainCost = 3
        // console.log(`${JSON.stringify(creep.name)}的${plainCost == 3 ? '消耗大于产出走道路' : '产出大于消耗走平原'}`);
        let pathByAStar = PathFinder.search(ori, target, { plainCost: plainCost, swampCost: 10, roomCallback: costM })
        return pathByAStar
    },
    /**跳点寻路 */
    findPathByJump: function (ori, target, option = {}) {
        let { range = 1, creep = null, byAutoBuild = false, ignoreCreeps = false, isSerialize = false, costM = null } = option
        let room = roomNameToObj(ori.roomName)
        costM = costM || PathFinder.CostMatrix.deserialize(Memory.rooms[ori.roomName]['terrain']['costMatrix'])
        // 只是单纯的需要路径，因此不需要传入creep
        if (!creep) {
            if (!byAutoBuild) {
                return room.findPath(ori, target, {
                    ignoreCreeps: ignoreCreeps,
                    plainCost: 1,
                    swampCost: 5,
                    costCallback: costM,
                    serialize: isSerialize
                })
            } else {
                return room.findPath(ori, target, {
                    ignoreCreeps: ignoreCreeps,
                    plainCost: 2,
                    swampCost: 8,
                    costCallback: costM,
                    serialize: isSerialize
                })
            }
        } else {
            let plain
            let swamp
            creep = creepNameToObj(creep)
            creepIsTired(creep) ? (plain = 3, swamp = 9) : (plain = 1, swamp = 5)
            // console.log(creep.name+'的'+plain==3?'疲劳高于移动力，优先走道路':'移动力高于疲劳，优先走平原');
            return room.findPath(ori, target, {
                ignoreCreeps: ignoreCreeps,
                plainCost: plain,
                swampCost: swamp,
                costCallback: costM,
                serialize: isSerialize
            })
        }
    }
}

export default roomTool